#==================================================
#	Climb
#==================================================
#  攀爬
#==================================================
# @datetime: 2021-9-29 14:43:19
#==================================================
extends "Action.gd"


## 抓到墙
signal grabbed
## 松手
signal loosen


## 向上攀爬速度
export var climb_speed : float = 0.0
## 减少重力速度的比值（如果为1，则代表没有重力）
export (float, 0.0, 1.0) var reduce_gravity = 1.0


# 是否开启功能了
var _is_starting : bool = false
# 控制的宿主
var _host: KinematicBody2D
# 减去的重力值（抓墙的时候的重力减少的值）
var _reduce_gravity : float = 0.0
# 是否状态是在墙上（用于判断是否抓到了墙，是否从墙上松手了）
var _state : bool = false



#==================================================
#   Set/Get
#==================================================
#(override)
func is_enabled() -> bool:
	return (
		.is_enabled() 
		&& _is_starting
	)



#==================================================
#   自定义方法
#==================================================
func _init_node() -> void:
	._init_node()
	_host = get_host() as KinematicBody2D
	register_to_function("Climb")


#(override)
func _init_data():
	._init_data()
	get_property().climb_speed = climb_speed


#(override)
func start(arg0):
	.start(arg0)
	_is_starting = true


#(override)
func stop():
	.stop()
	_is_starting = false


#(override)
func _process_execute(delta):
	if is_enabled():
		# 在墙上时，状态却没开启时
		if (
			_state != true
			&& _host.is_on_wall() 
			&& not _host.is_on_floor()
		):
			_state = true
			_on_wall()
		
		# 不在墙上或在地上，状态却开启时
		elif (
			_state
			&& (not _host.is_on_wall() || _host.is_on_floor())
		):
			_state = false
			_not_on_wall()
		
		# 如果是攀爬状态，则调用攀爬进程
		if _state:
			_climp_process(delta)


## 攀爬进程
func _climp_process(delta: float) -> void:
	# 当前爬墙有速度
	var vel := get_property().velocity as Vector2
	vel.y -= climb_speed * delta
	if climb_speed > 0:
		vel.y = max(vel.y, -climb_speed)
	elif climb_speed < 0:
		vel.y = min(vel.y, -climb_speed)
	get_property().velocity = vel


## 抓在墙上时
func _on_wall() -> void:
	# 减少并记录这个重力值
	var max_gravity = get_property().max_gravity
	_reduce_gravity = max_gravity * reduce_gravity
	max_gravity -= _reduce_gravity
	get_property().max_gravity = max_gravity
	
	# 重新设置当前重力的值不超过最大重力
	var current_gravity = get_property().velocity.y
	current_gravity = min(current_gravity, max_gravity)
	get_property().velocity.y = current_gravity
	
	# 下降速度不能超过 Gravity 速度
	if get_property().velocity.y > current_gravity:
		get_property().velocity.y = current_gravity
	emit_signal("grabbed")


## 墙上下来时
func _not_on_wall() -> void:
	# 还原最大值
	get_property().max_gravity += _reduce_gravity
	# 减去的重力归零
	_reduce_gravity = 0
	emit_signal("loosen")



